package com.brzjomo.secretiveworld.object.block;

import java.util.stream.Stream;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.DirectionProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.Half;
import net.minecraft.util.Direction;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;

public class FloatingBridgeBlock extends Block {

	public static final EnumProperty<Half> HALF = BlockStateProperties.HALF;
	public static final DirectionProperty FACING = HorizontalBlock.HORIZONTAL_FACING;
	public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
	
	public FloatingBridgeBlock(Properties properties) {
		super(properties);
		this.setDefaultState(this.stateContainer.getBaseState().with(FACING, Direction.NORTH).with(HALF, Half.BOTTOM).with(WATERLOGGED, Boolean.valueOf(false)));
	}

	private static final VoxelShape SHAPE_N = Stream.of(
			Block.makeCuboidShape(1, 0, 0, 15, 4, 3),
			Block.makeCuboidShape(1, 0, 5, 15, 4, 11),
			Block.makeCuboidShape(1, 0, 13, 15, 4, 16),
			Block.makeCuboidShape(0, 0, 0, 1, 1, 16),
			Block.makeCuboidShape(0, 3, 0, 1, 4, 16),
			Block.makeCuboidShape(0, 1, 15, 1, 3, 16),
			Block.makeCuboidShape(0, 1, 0, 1, 3, 1),
			Block.makeCuboidShape(0, 1, 13, 1, 3, 14),
			Block.makeCuboidShape(0, 1, 10, 1, 3, 11),
			Block.makeCuboidShape(0, 1, 5, 1, 3, 6),
			Block.makeCuboidShape(0, 1, 2, 1, 3, 3),
			Block.makeCuboidShape(0, 1, 1, 1, 3, 2),
			Block.makeCuboidShape(0, 1, 6, 1, 3, 10),
			Block.makeCuboidShape(0, 1, 14, 1, 3, 15),
			Block.makeCuboidShape(15, 0, 0, 16, 1, 16),
			Block.makeCuboidShape(15, 3, 0, 16, 4, 16),
			Block.makeCuboidShape(15, 1, 15, 16, 3, 16),
			Block.makeCuboidShape(15, 1, 0, 16, 3, 1),
			Block.makeCuboidShape(15, 1, 2, 16, 3, 3),
			Block.makeCuboidShape(15, 1, 5, 16, 3, 6),
			Block.makeCuboidShape(15, 1, 13, 16, 3, 14),
			Block.makeCuboidShape(15, 1, 10, 16, 3, 11),
			Block.makeCuboidShape(15, 1, 1, 16, 3, 2),
			Block.makeCuboidShape(15, 1, 14, 16, 3, 15),
			Block.makeCuboidShape(15, 1, 6, 16, 3, 10)
			).reduce((v1, v2) -> {return VoxelShapes.combineAndSimplify(v1, v2, IBooleanFunction.OR);}).get();
	
	private static final VoxelShape SHAPE_E = Stream.of(
			Block.makeCuboidShape(0, 0, 1, 3, 4, 15),
			Block.makeCuboidShape(5, 0, 1, 11, 4, 15),
			Block.makeCuboidShape(13, 0, 1, 16, 4, 15),
			Block.makeCuboidShape(0, 0, 15, 16, 1, 16),
			Block.makeCuboidShape(0, 3, 15, 16, 4, 16),
			Block.makeCuboidShape(15, 1, 15, 16, 3, 16),
			Block.makeCuboidShape(0, 1, 15, 1, 3, 16),
			Block.makeCuboidShape(13, 1, 15, 14, 3, 16),
			Block.makeCuboidShape(10, 1, 15, 11, 3, 16),
			Block.makeCuboidShape(5, 1, 15, 6, 3, 16),
			Block.makeCuboidShape(2, 1, 15, 3, 3, 16),
			Block.makeCuboidShape(1, 1, 15, 2, 3, 16),
			Block.makeCuboidShape(6, 1, 15, 10, 3, 16),
			Block.makeCuboidShape(14, 1, 15, 15, 3, 16),
			Block.makeCuboidShape(0, 0, 0, 16, 1, 1),
			Block.makeCuboidShape(0, 3, 0, 16, 4, 1),
			Block.makeCuboidShape(15, 1, 0, 16, 3, 1),
			Block.makeCuboidShape(0, 1, 0, 1, 3, 1),
			Block.makeCuboidShape(2, 1, 0, 3, 3, 1),
			Block.makeCuboidShape(5, 1, 0, 6, 3, 1),
			Block.makeCuboidShape(13, 1, 0, 14, 3, 1),
			Block.makeCuboidShape(10, 1, 0, 11, 3, 1),
			Block.makeCuboidShape(1, 1, 0, 2, 3, 1),
			Block.makeCuboidShape(14, 1, 0, 15, 3, 1),
			Block.makeCuboidShape(6, 1, 0, 10, 3, 1)
			).reduce((v1, v2) -> {return VoxelShapes.combineAndSimplify(v1, v2, IBooleanFunction.OR);}).get();
	
	private static final VoxelShape SHAPE_N_T = Stream.of(
			Block.makeCuboidShape(1, 12, 0, 15, 16, 3),
			Block.makeCuboidShape(1, 12, 5, 15, 16, 11),
			Block.makeCuboidShape(1, 12, 13, 15, 16, 16),
			Block.makeCuboidShape(0, 12, 0, 1, 13, 16),
			Block.makeCuboidShape(0, 15, 0, 1, 16, 16),
			Block.makeCuboidShape(0, 13, 15, 1, 15, 16),
			Block.makeCuboidShape(0, 13, 0, 1, 15, 1),
			Block.makeCuboidShape(0, 13, 13, 1, 15, 14),
			Block.makeCuboidShape(0, 13, 10, 1, 15, 11),
			Block.makeCuboidShape(0, 13, 5, 1, 15, 6),
			Block.makeCuboidShape(0, 13, 2, 1, 15, 3),
			Block.makeCuboidShape(0, 13, 1, 1, 15, 2),
			Block.makeCuboidShape(0, 13, 6, 1, 15, 10),
			Block.makeCuboidShape(0, 13, 14, 1, 15, 15),
			Block.makeCuboidShape(15, 12, 0, 16, 13, 16),
			Block.makeCuboidShape(15, 15, 0, 16, 16, 16),
			Block.makeCuboidShape(15, 13, 15, 16, 15, 16),
			Block.makeCuboidShape(15, 13, 0, 16, 15, 1),
			Block.makeCuboidShape(15, 13, 2, 16, 15, 3),
			Block.makeCuboidShape(15, 13, 5, 16, 15, 6),
			Block.makeCuboidShape(15, 13, 13, 16, 15, 14),
			Block.makeCuboidShape(15, 13, 10, 16, 15, 11),
			Block.makeCuboidShape(15, 13, 1, 16, 15, 2),
			Block.makeCuboidShape(15, 13, 14, 16, 15, 15),
			Block.makeCuboidShape(15, 13, 6, 16, 15, 10)
			).reduce((v1, v2) -> {return VoxelShapes.combineAndSimplify(v1, v2, IBooleanFunction.OR);}).get();
	
	private static final VoxelShape SHAPE_E_T = Stream.of(
			Block.makeCuboidShape(0, 12, 1, 3, 16, 15),
			Block.makeCuboidShape(5, 12, 1, 11, 16, 15),
			Block.makeCuboidShape(13, 12, 1, 16, 16, 15),
			Block.makeCuboidShape(0, 12, 15, 16, 13, 16),
			Block.makeCuboidShape(0, 15, 15, 16, 16, 16),
			Block.makeCuboidShape(15, 13, 15, 16, 15, 16),
			Block.makeCuboidShape(0, 13, 15, 1, 15, 16),
			Block.makeCuboidShape(13, 13, 15, 14, 15, 16),
			Block.makeCuboidShape(10, 13, 15, 11, 15, 16),
			Block.makeCuboidShape(5, 13, 15, 6, 15, 16),
			Block.makeCuboidShape(2, 13, 15, 3, 15, 16),
			Block.makeCuboidShape(1, 13, 15, 2, 15, 16),
			Block.makeCuboidShape(6, 13, 15, 10, 15, 16),
			Block.makeCuboidShape(14, 13, 15, 15, 15, 16),
			Block.makeCuboidShape(0, 12, 0, 16, 13, 1),
			Block.makeCuboidShape(0, 15, 0, 16, 16, 1),
			Block.makeCuboidShape(15, 13, 0, 16, 15, 1),
			Block.makeCuboidShape(0, 13, 0, 1, 15, 1),
			Block.makeCuboidShape(2, 13, 0, 3, 15, 1),
			Block.makeCuboidShape(5, 13, 0, 6, 15, 1),
			Block.makeCuboidShape(13, 13, 0, 14, 15, 1),
			Block.makeCuboidShape(10, 13, 0, 11, 15, 1),
			Block.makeCuboidShape(1, 13, 0, 2, 15, 1),
			Block.makeCuboidShape(14, 13, 0, 15, 15, 1),
			Block.makeCuboidShape(6, 13, 0, 10, 15, 1)
			).reduce((v1, v2) -> {return VoxelShapes.combineAndSimplify(v1, v2, IBooleanFunction.OR);}).get();
	
	@Override
	public VoxelShape getShape(BlockState stateIn, IBlockReader worldIn, BlockPos posIn, ISelectionContext contextIn) {
		if (stateIn.get(HALF) == Half.TOP) {
			switch (stateIn.get(FACING)) {
			case NORTH:
				return SHAPE_N_T;
			case SOUTH:
				return SHAPE_N_T;
			case EAST:
				return SHAPE_E_T;
			case WEST:
				return SHAPE_E_T;
			default:
				return SHAPE_N_T;
			}
		} else {
			switch (stateIn.get(FACING)) {
			case NORTH:
				return SHAPE_N;
			case SOUTH:
				return SHAPE_N;
			case EAST:
				return SHAPE_E;
			case WEST:
				return SHAPE_E;
			default:
				return SHAPE_N;
			}
		}
		
	}
	
	public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) {
		if (!worldIn.isRemote) {
	    	  if (state.get(WATERLOGGED)) {
	    		  worldIn.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(worldIn));
	    	  }
		}
	}
	
	public BlockState getStateForPlacement(BlockItemUseContext context) {
		BlockState blockstate = this.getDefaultState();
		Direction direction = context.getFace();
		IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos());
		if (!context.replacingClickedOnBlock() && direction.getAxis().isHorizontal()) {
			blockstate = blockstate.with(FACING, direction).with(HALF, context.getHitVec().y - (double)context.getPos().getY() > 0.5D ? Half.TOP : Half.BOTTOM);
		} else {
			blockstate = blockstate.with(FACING, context.getPlacementHorizontalFacing().getOpposite()).with(HALF, direction == Direction.UP ? Half.BOTTOM : Half.TOP);
		}
		return blockstate.with(WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
	}
	
	//增加属性
		@Override
		protected void fillStateContainer(Builder<Block, BlockState> builder) {
			builder.add(FACING, HALF, WATERLOGGED);
		}
		
		@SuppressWarnings("deprecation")
		public IFluidState getFluidState(BlockState state) {
			return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state);
		}
		
		@SuppressWarnings("deprecation")
		public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) {
			if (stateIn.get(WATERLOGGED)) {
				worldIn.getPendingFluidTicks().scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickRate(worldIn));
			}

			return super.updatePostPlacement(stateIn, facing, facingState, worldIn, currentPos, facingPos);
		}
		
		// 旋转和镜像支持
		public BlockState rotate(BlockState state, Rotation rot) {
			return state.with(FACING, rot.rotate(state.get(FACING)));
		}

		public BlockState mirror(BlockState state, Mirror mirrorIn) {
			return state.rotate(mirrorIn.toRotation(state.get(FACING)));
		}

		// 活塞推动支持
		public PushReaction getPushReaction(BlockState state) {
			return PushReaction.NORMAL;
		}
}
